package test

import (
	"errors"
	"fmt"
	"gorm/internal/database"
	"gorm/internal/domain"

	"gorm.io/gorm"
)

// 手动事务
func CreateOrderManual(db *gorm.DB, userID, productID uint) error {

	// 1.开启事务
	tx := db.Begin()
	if tx.Error != nil {
		return tx.Error
	}

	// 2.检查库存(在事务中执行所有操作)
	var product domain.Product
	if err := tx.Set("gorm:query_option", "FOR UPDATE").First(product, productID).Error; err != nil {
		tx.Rollback() // 查找失败，回滚
		return errors.New("商品不存在")
	}

	if product.Stock == 0 {
		tx.Rollback() // 库存不足，回滚
		return errors.New("商品库存不足")
	}

	// 3.扣减库存
	if err := tx.Model(&product).Update("stock", gorm.Expr("stock - 1")).Error; err != nil {
		tx.Rollback() // 更新失败，回滚
		return err
	}

	// 4.创建订单
	order := domain.Order{UserID: userID, ProductID: productID, Status: "processing"}
	if err := tx.Create(&order).Error; err != nil {
		tx.Rollback() // 创建订单失败，回滚
		return err
	}

	/// 5.提交事务
	return tx.Commit().Error

}

func CreateOrderManualMain() {
	db := database.DB

	db.Create(&domain.Product{Code: "L1214", Price: 500, Stock: 10})
	fmt.Println("-- 尝试成功下单 --")
	var product domain.Product
	db.First(&product, "code = ?", "L1214")

	err := CreateOrderManual(db, 1, product.ID)
	if err != nil {
		fmt.Printf("下单失败: %v\n", err)
	} else {
		fmt.Println("下单成功！")
		var updatedProduct domain.Product
		db.First(&updatedProduct, product.ID)
		fmt.Printf("商品 %s 的最新库存是: %d\n", updatedProduct.Code, updatedProduct.Stock)
	}
}

// gorm自动事务
func CreateOrderAutomatic(db *gorm.DB, userID uint, productID uint) error {
	// GORM 会自动处理事务的开始、提交和回滚
	err := db.Transaction(func(tx *gorm.DB) error {
		// 1.检查库存并锁定
		var product domain.Product
		if err := tx.Set("gorm:query_option", "FOR UPDATE").First(&product, productID).Error; err != nil {
			return errors.New("商品不存在")
		}

		if product.Stock == 0 {
			return errors.New("商品库存不足") // 返回错误，gorm自动回滚
		}

		// 2.扣减库存
		if err := tx.Model(&product).Update("stock", gorm.Expr("stock - 1")).Error; err != nil {
			return err
		}

		// 3.创建订单
		order := domain.Order{UserID: userID, ProductID: productID, Status: "processing"}
		if err := tx.Create(&order).Error; err != nil {
			return err
		}
		return nil

	})
	return err
}

func CreateOrderAutomaticMain() {
	db := database.DB

	db.Create(&domain.Product{Code: "L1214", Price: 500, Stock: 10})
	fmt.Println("-- 尝试成功下单 --")
	var product domain.Product
	db.First(&product, "code = ?", "L1214")

	err := CreateOrderAutomatic(db, 1, product.ID)
	if err != nil {
		fmt.Printf("下单失败: %v\n", err)
	} else {
		fmt.Println("下单成功！")
		var updatedProduct domain.Product
		db.First(&updatedProduct, product.ID)
		fmt.Printf("商品 %s 的最新库存是: %d\n", updatedProduct.Code, updatedProduct.Stock)
	}
}
